package com.zgl.gemduel.service;

import com.zgl.gemduel.model.*;
import com.zgl.gemduel.constants.staticSource;
import com.zgl.gemduel.utils.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class RoomResourceService {

    @Autowired
    private RedisService redisService;

    @Autowired
    private RoomResourceNotificationService notificationService;

    /**
     * 初始化房间资源
     * @param roomId 房间ID
     * @return 初始化后的房间资源
     */
    public RoomResource initializeRoomResource(String roomId) {
        RoomResource roomResource = new RoomResource();
        
        // 设置初始状态
        roomResource.setStatus("waiting");
        roomResource.setPlayerIps(new ArrayList<>());
        roomResource.setRound(0);
        
        // 初始化游戏配置
        GameConfig config = createDefaultGameConfig();
        roomResource.setGameConfig(config);
        
        // 初始化玩家面板
        roomResource.setPlayerPanels(new HashMap<>());
        
        // 初始化宝石资源
        initializeGemResources(roomResource);
        
        // 初始化卡片资源
        initializeCardResources(roomResource);
        
        // 初始化黑袋（已使用的宝石）
        roomResource.setBlackBag(new ArrayList<>());
        
        // 初始化玩家相关资源
        roomResource.setKeepCards(new HashMap<>());
        roomResource.setBuyCards(new HashMap<>());

        // 设置是否已填充
        roomResource.setFilled(false);
        // 设置玩家是否可以使用特权
        roomResource.setCanUsePrivilege(false);
        // 设置玩家是否可以补充宝石盘
        roomResource.setCanRefillGemBoard(false);

        // 初始化特权数
        roomResource.setPublicPrivilege(3);

        // 将房间资源存储到Redis
        redisService.set("roomResource:" + roomId, roomResource);
        
        // 通知客户端房间资源已更新
        notificationService.notifyRoomResourceUpdate(roomId, roomResource);
        
        return roomResource;
    }
    
    /**
     * 初始化宝石资源
     * @param roomResource 房间资源
     */
    private void initializeGemResources(RoomResource roomResource) {
        // 初始化宝石源
        List<gem> gemSource = new ArrayList<>();
        for (gem gem : staticSource.gemStaticSource) {
            gemSource.add(cloneGem(gem));
        }
        roomResource.setGemSource(gemSource);
        
        // 将宝石源的宝石ID随机乱序初始化到gemPosition数组中
        List<String> gemPositions = new ArrayList<>(Collections.nCopies(25, "-1"));
        
        // 创建宝石ID列表
        List<String> gemIds = new ArrayList<>();
        for (gem gem : gemSource) {
            gemIds.add(gem.getId());
        }
        
        // 随机打乱宝石ID列表
        Collections.shuffle(gemIds);
        
        // 将前25个宝石ID填充到gemPositions中
        int size = Math.min(gemIds.size(), 25);
        for (int i = 0; i < size; i++) {
            gemPositions.set(i, gemIds.get(i));
        }
        
        roomResource.setGemPositon(gemPositions);
    }
    
    /**
     * 初始化卡片资源
     * @param roomResource 房间资源
     */
    private void initializeCardResources(RoomResource roomResource) {
        // 按等级分类卡片
        List<card> level1Cards = new ArrayList<>();
        List<card> level2Cards = new ArrayList<>();
        List<card> level3Cards = new ArrayList<>();
        List<card> level4Cards = new ArrayList<>();
        
        for (card card : staticSource.cardStaticSource) {
            switch (card.getLevel()) {
                case 1:
                    level1Cards.add(cloneCard(card));
                    break;
                case 2:
                    level2Cards.add(cloneCard(card));
                    break;
                case 3:
                    level3Cards.add(cloneCard(card));
                    break;
                case 4:
                    level4Cards.add(cloneCard(card));
                    break;
            }
        }

        // 对卡片的show进行修改 类型4全置为true 等级为3的有3张置为true 等级为2的有4张 等级为1的有5张
        // 等级4的卡片全部设置为show=true（仅对buyable为true的卡片）
        for (card card : level4Cards) {
            card.setShow(true);
        }
        
        // 等级3的卡片选择3张设置为show=true（仅对buyable为true的卡片）
        setRandomCardsToShow(level3Cards, 3);
        
        // 等级2的卡片选择4张设置为show=true（仅对buyable为true的卡片）
        setRandomCardsToShow(level2Cards, 4);
        
        // 等级1的卡片选择5张设置为show=true（仅对buyable为true的卡片）
        setRandomCardsToShow(level1Cards, 5);

        roomResource.setCardListA(level1Cards);
        roomResource.setCardListB(level2Cards);
        roomResource.setCardListC(level3Cards);
        roomResource.setCardListD(level4Cards);
    }

    /**
     * 随机选择指定数量的卡片设置为show=true（仅对buyable为true且keepable为false的卡片）
     * @param cards 卡片列表
     * @param num 数量
     */
    private void setRandomCardsToShow(List<card> cards, int num) {
        Random random = new Random();
        
        // 过滤出buyable为true且keepable为true的卡片
        List<card> eligibleCards = new ArrayList<>();
        for (card card : cards) {
            if (card.isBuyable() && card.isKeepable() && !card.isShow()) {
                eligibleCards.add(card);
            }
        }
        
        // 如果没有符合条件的卡片，则直接返回
        if (eligibleCards.isEmpty()) {
            return;
        }
        
        // 确保选择数量在范围内（这里min和max相同，所以直接使用）
        int selectCount = Math.min(num, eligibleCards.size());
        
        // 创建索引列表并打乱
        List<Integer> indices = new ArrayList<>();
        for (int i = 0; i < eligibleCards.size(); i++) {
            indices.add(i);
        }
        Collections.shuffle(indices);
        
        // 设置前selectCount个卡片的show为true
        for (int i = 0; i < selectCount; i++) {
            eligibleCards.get(indices.get(i)).setShow(true);
        }
    }
    
    /**
     * 克隆宝石对象
     * @param original 原始宝石
     * @return 克隆的宝石
     */
    private gem cloneGem(gem original) {
        gem cloned = new gem();
        cloned.setId(original.getId());
        cloned.setColor(original.getColor());
        return cloned;
    }

    /**
     * 玩家拿取宝石
     * @param roomId 房间ID
     * @param playerIp 玩家IP
     * @param gemPositionIndices 宝石在宝石盘中的位置索引列表
     */
    public void takeGems(String roomId, String playerIp, List<Integer> gemPositionIndices) {
        RoomResource roomResource = getRoomResource(roomId);
        if (roomResource == null || !"playing".equals(roomResource.getStatus())) {
            return;
        }

        // 检查是否是当前回合玩家
        if (!playerIp.equals(roomResource.getCurrentPlayerIp())) {
            return;
        }

        // 检查宝石数量是否在1-3个之间
        if (gemPositionIndices == null || gemPositionIndices.size() < 1 || gemPositionIndices.size() > 3) {
            return;
        }

        // 检查宝石位置索引是否有效
        List<String> gemPositions = roomResource.getGemPositon();
        if (gemPositions == null) {
            return;
        }

        // 验证所有位置索引是否有效且对应位置有宝石
        List<String> gemIdsToTake = new ArrayList<>();
        for (Integer index : gemPositionIndices) {
            if (index < 0 || index >= gemPositions.size()) {
                return; // 位置索引无效
            }
            String gemId = gemPositions.get(index);
            if ("-1".equals(gemId)) {
                return; // 该位置没有宝石
            }
            gemIdsToTake.add(gemId);
        }

        // 执行拿取宝石操作
        for (int i = 0; i < gemPositionIndices.size(); i++) {
            Integer index = gemPositionIndices.get(i);
            String gemId = gemIdsToTake.get(i);
            
            // 从宝石盘拿取宝石并归玩家所有
            collectGemFromBoard(roomResource, playerIp, index, gemId);
        }

        // 更新Redis中的房间资源
        updateRoomResource(roomId, roomResource);
        
        notificationService.notifyRoomCommand(roomId, "TAKE_GEMS_SUCCESS");

        // 进入下一回合
        startNewRound(roomId);
        
        // 为下一玩家设置操作权限
        setupNextPlayerPermissions(roomId);

    }

    /**
     * 从宝石盘拿取宝石并归玩家所有（可复用的方法）
     * @param roomResource 房间资源
     * @param playerIp 玩家IP
     * @param gemPositionIndex 宝石在宝石盘中的位置索引
     * @param gemId 宝石ID
     */
    public void collectGemFromBoard(RoomResource roomResource, String playerIp, int gemPositionIndex, String gemId) {
        // 将宝石位置设置为-1（表示该位置已空）
        List<String> gemPositions = roomResource.getGemPositon();
        gemPositions.set(gemPositionIndex, "-1");

        // 将宝石添加到玩家的已收集宝石列表中
        Map<String, userPanel> playerPanels = roomResource.getPlayerPanels();
        userPanel playerPanel = playerPanels.get(playerIp);
        if (playerPanel != null) {
            List<gem> collectedGems = playerPanel.getCollectedGems();
            if (collectedGems == null) {
                collectedGems = new ArrayList<>();
                playerPanel.setCollectedGems(collectedGems);
            }

            // 查找宝石对象并添加到玩家收集列表
            gem gem = findGemById(roomResource.getGemSource(), gemId);
            if (gem != null) {
                collectedGems.add(cloneGem(gem));
            }

            // 更新玩家面板信息
            updatePlayerGemCounts(playerPanel, gem);
        }
    }

    /**
     * 根据ID查找宝石
     * @param gemSource 宝石源列表
     * @param gemId 宝石ID
     * @return 宝石对象，如果未找到则返回null
     */
    private gem findGemById(List<gem> gemSource, String gemId) {
        if (gemSource == null || gemId == null) {
            return null;
        }

        for (gem gem : gemSource) {
            if (gemId.equals(gem.getId())) {
                return gem;
            }
        }
        return null;
    }

    /**
     * 更新玩家宝石计数
     * @param playerPanel 玩家面板
     * @param gem 宝石
     */
    private void updatePlayerGemCounts(userPanel playerPanel, gem gem) {
        if (gem == null || playerPanel == null) {
            return;
        }

        // 根据宝石颜色更新对应的宝石计数
        switch (gem.getColor()) {
            case red:
                playerPanel.setGemNumRed(playerPanel.getGemNumRed() + 1);
                break;
            case blue:
                playerPanel.setGemNumBlue(playerPanel.getGemNumBlue() + 1);
                break;
            case green:
                playerPanel.setGemNumGreen(playerPanel.getGemNumGreen() + 1);
                break;
            case white:
                playerPanel.setGemNumWhite(playerPanel.getGemNumWhite() + 1);
                break;
            case black:
                playerPanel.setGemNumBlack(playerPanel.getGemNumBlack() + 1);
                break;
            case gold:
                playerPanel.setGemNumGold(playerPanel.getGemNumGold() + 1);
                break;
            case pink:
                playerPanel.setGemNumPink(playerPanel.getGemNumPink() + 1);
                break;
        }

        // 更新宝石总数
        playerPanel.setGemNumTotal(playerPanel.getGemNumTotal() + 1);
    }

    /**
     * 玩家购买卡片
     * @param roomId 房间ID
     * @param playerIp 玩家IP
     * @param cardId 卡片ID
     */
    public void buyCard(String roomId, String playerIp, String cardId) {
        RoomResource roomResource = getRoomResource(roomId);
        if (roomResource == null || !"playing".equals(roomResource.getStatus())) {
            return;
        }

        // 检查是否是当前回合玩家
        if (!playerIp.equals(roomResource.getCurrentPlayerIp())) {
            return;
        }

        // 查找要购买的卡片
        card cardToBuy = findCardById(roomResource, cardId);
        if (cardToBuy == null || !cardToBuy.isBuyable() || !cardToBuy.isShow()) {
            return; // 卡片不存在、不可购买或未显示
        }

        // 获取玩家面板
        Map<String, userPanel> playerPanels = roomResource.getPlayerPanels();
        userPanel playerPanel = playerPanels.get(playerIp);
        if (playerPanel == null) {
            return;
        }

        // 检查玩家是否有足够的宝石购买卡片
        if (!hasEnoughGemsToBuyCard(playerPanel, cardToBuy)) {
            return; // 宝石不足
        }

        // 执行购买操作
        // 1. 从玩家宝石中扣除消耗
        deductGemsForCard(playerPanel, cardToBuy);

        // 2. 将卡片添加到玩家已购买列表
        List<card> boughtCards = playerPanel.getCardBought();
        if (boughtCards == null) {
            boughtCards = new ArrayList<>();
            playerPanel.setCardBought(boughtCards);
        }
        boughtCards.add(cloneCard(cardToBuy));

        // 3. 如果该卡片在玩家的保留列表中，则从保留列表中移除
        List<card> keptCards = playerPanel.getCardKept();
        if (keptCards != null) {
            keptCards.removeIf(card -> cardId.equals(card.getId()));
        }

        // 4. 更新卡片状态
        cardToBuy.setShow(false);
        cardToBuy.setBuyable(false);

        // 4. 更新玩家面板信息
        // 增加皇冠数
        playerPanel.setCrownsNum(playerPanel.getCrownsNum() + cardToBuy.getCrownsNum());
        
        // 增加分数
        playerPanel.setScore(playerPanel.getScore() + cardToBuy.getScore());
        
        // 增加折扣
        playerPanel.setDiscountRed(playerPanel.getDiscountRed() + cardToBuy.getDiscountRed());
        playerPanel.setDiscountBlue(playerPanel.getDiscountBlue() + cardToBuy.getDiscountBlue());
        playerPanel.setDiscountGreen(playerPanel.getDiscountGreen() + cardToBuy.getDiscountGreen());
        playerPanel.setDiscountWhite(playerPanel.getDiscountWhite() + cardToBuy.getDiscountWhite());
        playerPanel.setDiscountBlack(playerPanel.getDiscountBlack() + cardToBuy.getDiscountBlack());

        // 5. 从相同等级的卡片堆中随机将一个show值为false的卡片置为show=true
        revealNextCard(roomResource, cardToBuy.getLevel());

        // 6. 处理额外奖励
        cardToBuy.processReward(notificationService, roomId, playerIp);

        // 更新Redis中的房间资源
        updateRoomResource(roomId, roomResource);

        // TODO 若该卡片有皇冠数量 则进行判断 若买了卡片后皇冠数集齐3个或6个 则通知前端可以领取类型四的卡片
        // 若该卡片有皇冠数量，则进行判断
        if (cardToBuy.getCrownsNum() > 0) {
            // 检查购买后玩家的皇冠数是否为3或6
            int currentCrowns = playerPanel.getCrownsNum();
            if (currentCrowns >= 3 || currentCrowns >= 6) {
                // 通知前端可以领取类型四的卡片
                notificationService.notifyRoomCommand(roomId, "CAN_CLAIM_LEVEL4_CARD");
            }
        }
        
        // TODO 进行游戏结果判断
        // 1. 玩家购买的卡片中某种颜色折扣的卡片总分数达到10
        // 2. 玩家总分数达到了20
        // 3. 玩家的皇冠数达到了10
        
        // 检查游戏结束条件
        checkGameEndConditions(roomResource, roomId, playerIp);
        
        // 进入下一回合
        startNewRound(roomId);
        
        // 为下一玩家设置操作权限
        setupNextPlayerPermissions(roomId);

        notificationService.notifyRoomCommand(roomId, "BUY_CARD_SUCCESS");
    }

    /**
     * 玩家购买卡片（支持玩家选择宝石作为支付筹码）
     * @param roomId 房间ID
     * @param playerIp 玩家IP
     * @param cardId 卡片ID
     * @param gemIds 玩家选择的宝石ID列表
     */
    public void buyCardWithGems(String roomId, String playerIp, String cardId, List<String> gemIds) {
        RoomResource roomResource = getRoomResource(roomId);
        if (roomResource == null || !"playing".equals(roomResource.getStatus())) {
            return;
        }

        // 检查是否是当前回合玩家
        if (!playerIp.equals(roomResource.getCurrentPlayerIp())) {
            return;
        }

        // 查找要购买的卡片
        card cardToBuy = findCardById(roomResource, cardId);
        if (cardToBuy == null || !cardToBuy.isBuyable()) {
            return; // 卡片不存在、不可购买或未显示
        }

        // 获取玩家面板
        Map<String, userPanel> playerPanels = roomResource.getPlayerPanels();
        userPanel playerPanel = playerPanels.get(playerIp);
        if (playerPanel == null) {
            return;
        }

        // 验证玩家选择的宝石是否符合卡片费用需求
        if (!validateGemPayment(playerPanel, cardToBuy, gemIds, roomResource.getGemSource())) {
            return; // 宝石不符合费用需求
        }

        // 执行购买操作
        // 1. 从玩家宝石中扣除消耗（使用选择的宝石）
        List<gem> paidGems = deductGemsForCardWithSelection(playerPanel, cardToBuy, gemIds, roomResource.getGemSource());

        // 2. 将支付的宝石添加到黑袋中
        if (roomResource.getBlackBag() == null) {
            roomResource.setBlackBag(new ArrayList<>());
        }
        roomResource.getBlackBag().addAll(paidGems);

        // 3. 将卡片添加到玩家已购买列表
        List<card> boughtCards = playerPanel.getCardBought();
        if (boughtCards == null) {
            boughtCards = new ArrayList<>();
            playerPanel.setCardBought(boughtCards);
        }
        boughtCards.add(cloneCard(cardToBuy));

        // 4. 如果该卡片在玩家的保留列表中，则从保留列表中移除
        List<card> keptCards = playerPanel.getCardKept();
        if (keptCards != null) {
            keptCards.removeIf(card -> cardId.equals(card.getId()));
        }

        // 5. 更新卡片状态
        cardToBuy.setShow(false);
        cardToBuy.setBuyable(false);

        // 5. 更新玩家面板信息
        // 增加皇冠数
        playerPanel.setCrownsNum(playerPanel.getCrownsNum() + cardToBuy.getCrownsNum());
        
        // 增加分数
        playerPanel.setScore(playerPanel.getScore() + cardToBuy.getScore());
        
        // 增加折扣
        playerPanel.setDiscountRed(playerPanel.getDiscountRed() + cardToBuy.getDiscountRed());
        playerPanel.setDiscountBlue(playerPanel.getDiscountBlue() + cardToBuy.getDiscountBlue());
        playerPanel.setDiscountGreen(playerPanel.getDiscountGreen() + cardToBuy.getDiscountGreen());
        playerPanel.setDiscountWhite(playerPanel.getDiscountWhite() + cardToBuy.getDiscountWhite());
        playerPanel.setDiscountBlack(playerPanel.getDiscountBlack() + cardToBuy.getDiscountBlack());

        // 6. 从相同等级的卡片堆中随机将一个show值为false的卡片置为show=true
        revealNextCard(roomResource, cardToBuy.getLevel());

        // 7. 处理额外奖励
        cardToBuy.processReward(notificationService, roomId, playerIp);

        // 更新Redis中的房间资源
        updateRoomResource(roomId, roomResource);

        // TODO 若该卡片有皇冠数量 则进行判断 若买了卡片后皇冠数集齐3个或6个 则通知前端可以领取类型四的卡片
        // 若该卡片有皇冠数量，则进行判断
        if (cardToBuy.getCrownsNum() > 0) {
            // 检查购买后玩家的皇冠数是否为3或6
            int currentCrowns = playerPanel.getCrownsNum();
            if (currentCrowns >= 3 || currentCrowns >= 6) {
                // 通知前端可以领取类型四的卡片
                notificationService.notifyRoomCommand(roomId, "CAN_CLAIM_LEVEL4_CARD");
            }
        }
        
        // TODO 进行游戏结果判断
        // 1. 玩家购买的卡片中某种颜色折扣的卡片总分数达到10
        // 2. 玩家总分数达到了20
        // 3. 玩家的皇冠数达到了10
        
        // 检查游戏结束条件
        checkGameEndConditions(roomResource, roomId, playerIp);

        notificationService.notifyRoomCommand(roomId, "BUY_CARD_SUCCESS");

        // 进入下一回合
        startNewRound(roomId);
        
        // 为下一玩家设置操作权限
        setupNextPlayerPermissions(roomId);
    }

    /**
     * 验证玩家选择的宝石是否符合卡片费用需求
     * @param playerPanel 玩家面板
     * @param card 卡片
     * @param gemIds 玩家选择的宝石ID列表
     * @param gemSource 宝石源
     * @return 是否符合费用需求
     */
    private boolean validateGemPayment(userPanel playerPanel, card card, List<String> gemIds, List<gem> gemSource) {
        if (gemIds == null || gemIds.isEmpty()) {
            return false;
        }

        // 统计玩家选择的宝石
        Map<GemColor, Integer> selectedGems = new HashMap<>();
        for (String gemId : gemIds) {
            gem gem = findGemById(gemSource, gemId);
            if (gem != null) {
                selectedGems.put(gem.getColor(), selectedGems.getOrDefault(gem.getColor(), 0) + 1);
            }
        }

        // 计算实际需要的宝石数量（扣除折扣后）
        int requiredRed = Math.max(0, card.getCostRed() - playerPanel.getDiscountRed());
        int requiredBlue = Math.max(0, card.getCostBlue() - playerPanel.getDiscountBlue());
        int requiredGreen = Math.max(0, card.getCostGreen() - playerPanel.getDiscountGreen());
        int requiredWhite = Math.max(0, card.getCostWhite() - playerPanel.getDiscountWhite());
        int requiredBlack = Math.max(0, card.getCostBlack() - playerPanel.getDiscountBlack());
        int requiredPink = Math.max(0, card.getCostPink()); // 粉色宝石没有折扣

        // 计算总需求
        int totalRequired = requiredRed + requiredBlue + requiredGreen + requiredWhite + requiredBlack + requiredPink;
        
        // 计算玩家拥有的非金色宝石总数
        int nonGoldGems = playerPanel.getGemNumRed() + playerPanel.getGemNumBlue() + playerPanel.getGemNumGreen() + 
                          playerPanel.getGemNumWhite() + playerPanel.getGemNumBlack() + playerPanel.getGemNumPink();
        
        // 计算玩家拥有的金色宝石数量
        int goldGems = playerPanel.getGemNumGold();
        
        // 检查是否有足够的宝石（金色宝石可以作为任意颜色使用）
        return nonGoldGems + goldGems >= totalRequired;
    }

    /**
     * 从玩家宝石中扣除购买卡片所需的宝石（使用玩家选择的宝石）
     * @param playerPanel 玩家面板
     * @param card 卡片
     * @param gemIds 玩家选择的宝石ID列表
     * @param gemSource 宝石源
     * @return 被扣除的宝石列表
     */
    private List<gem> deductGemsForCardWithSelection(userPanel playerPanel, card card, List<String> gemIds, List<gem> gemSource) {
        List<gem> paidGems = new ArrayList<>();

        // 直接扣除玩家选择的宝石，不进行验证
        Map<GemColor, Integer> selectedGems = new HashMap<>();
        for (String gemId : gemIds) {
            gem gem = findGemById(gemSource, gemId);
            if (gem != null) {
                selectedGems.put(gem.getColor(), selectedGems.getOrDefault(gem.getColor(), 0) + 1);
                paidGems.add(cloneGem(gem));
            }
        }

        // 扣除选择的非金色宝石
        int usedRed = selectedGems.getOrDefault(GemColor.red, 0);
        int usedBlue = selectedGems.getOrDefault(GemColor.blue, 0);
        int usedGreen = selectedGems.getOrDefault(GemColor.green, 0);
        int usedWhite = selectedGems.getOrDefault(GemColor.white, 0);
        int usedBlack = selectedGems.getOrDefault(GemColor.black, 0);
        int usedPink = selectedGems.getOrDefault(GemColor.pink, 0);
        int usedGold = selectedGems.getOrDefault(GemColor.gold, 0);

        // 更新玩家宝石计数
        playerPanel.setGemNumRed(playerPanel.getGemNumRed() - usedRed);
        playerPanel.setGemNumBlue(playerPanel.getGemNumBlue() - usedBlue);
        playerPanel.setGemNumGreen(playerPanel.getGemNumGreen() - usedGreen);
        playerPanel.setGemNumWhite(playerPanel.getGemNumWhite() - usedWhite);
        playerPanel.setGemNumBlack(playerPanel.getGemNumBlack() - usedBlack);
        playerPanel.setGemNumPink(playerPanel.getGemNumPink() - usedPink);
        playerPanel.setGemNumGold(playerPanel.getGemNumGold() - usedGold);

        // 从玩家已收集的宝石列表中移除已使用的宝石
        List<gem> collectedGems = playerPanel.getCollectedGems();
        if (collectedGems != null) {
            gemIds.stream().forEach(gemId -> {
                collectedGems.removeIf(item -> item.getId().equals(gemId));
            });
        }

        // 更新宝石总数
        int totalDeducted = usedRed + usedBlue + usedGreen + usedWhite + usedBlack + usedPink + usedGold;
        playerPanel.setGemNumTotal(playerPanel.getGemNumTotal() - totalDeducted);

        return paidGems;
    }

    /**
     * 根据ID查找卡片
     * @param roomResource 房间资源
     * @param cardId 卡片ID
     * @return 卡片对象，如果未找到则返回null
     */
    private card findCardById(RoomResource roomResource, String cardId) {
        if (roomResource == null || cardId == null) {
            return null;
        }

        // 在所有等级的卡片列表中查找
        List<card> allCards = new ArrayList<>();
        if (roomResource.getCardListA() != null) allCards.addAll(roomResource.getCardListA());
        if (roomResource.getCardListB() != null) allCards.addAll(roomResource.getCardListB());
        if (roomResource.getCardListC() != null) allCards.addAll(roomResource.getCardListC());
        if (roomResource.getCardListD() != null) allCards.addAll(roomResource.getCardListD());

        for (card card : allCards) {
            if (cardId.equals(card.getId())) {
                return card;
            }
        }
        return null;
    }

    /**
     * 检查玩家是否有足够的宝石购买卡片
     * @param playerPanel 玩家面板
     * @param card 卡片
     * @return 是否有足够的宝石
     */
    private boolean hasEnoughGemsToBuyCard(userPanel playerPanel, card card) {
        // 计算实际需要的宝石数量（扣除折扣后）
        int requiredRed = Math.max(0, card.getCostRed() - playerPanel.getDiscountRed());
        int requiredBlue = Math.max(0, card.getCostBlue() - playerPanel.getDiscountBlue());
        int requiredGreen = Math.max(0, card.getCostGreen() - playerPanel.getDiscountGreen());
        int requiredWhite = Math.max(0, card.getCostWhite() - playerPanel.getDiscountWhite());
        int requiredBlack = Math.max(0, card.getCostBlack() - playerPanel.getDiscountBlack());
        int requiredPink = Math.max(0, card.getCostPink()); // 粉色宝石没有折扣

        // 计算总需求
        int totalRequired = requiredRed + requiredBlue + requiredGreen + requiredWhite + requiredBlack + requiredPink;
        
        // 计算玩家拥有的非金色宝石总数
        int nonGoldGems = playerPanel.getGemNumRed() + playerPanel.getGemNumBlue() + playerPanel.getGemNumGreen() + 
                          playerPanel.getGemNumWhite() + playerPanel.getGemNumBlack() + playerPanel.getGemNumPink();
        
        // 计算玩家拥有的金色宝石数量
        int goldGems = playerPanel.getGemNumGold();
        
        // 检查是否有足够的宝石（金色宝石可以作为任意颜色使用）
        return nonGoldGems + goldGems >= totalRequired;
    }

    /**
     * 从玩家宝石中扣除购买卡片所需的宝石
     * @param playerPanel 玩家面板
     * @param card 卡片
     */
    private void deductGemsForCard(userPanel playerPanel, card card) {
        // 计算实际需要的宝石数量（扣除折扣后）
        int requiredRed = Math.max(0, card.getCostRed() - playerPanel.getDiscountRed());
        int requiredBlue = Math.max(0, card.getCostBlue() - playerPanel.getDiscountBlue());
        int requiredGreen = Math.max(0, card.getCostGreen() - playerPanel.getDiscountGreen());
        int requiredWhite = Math.max(0, card.getCostWhite() - playerPanel.getDiscountWhite());
        int requiredBlack = Math.max(0, card.getCostBlack() - playerPanel.getDiscountBlack());
        int requiredPink = Math.max(0, card.getCostPink()); // 粉色宝石没有折扣

        // 扣除具体的宝石
        int remainingRed = Math.max(0, playerPanel.getGemNumRed() - requiredRed);
        int deductedRed = playerPanel.getGemNumRed() - remainingRed;
        playerPanel.setGemNumRed(remainingRed);
        requiredRed -= deductedRed;

        int remainingBlue = Math.max(0, playerPanel.getGemNumBlue() - requiredBlue);
        int deductedBlue = playerPanel.getGemNumBlue() - remainingBlue;
        playerPanel.setGemNumBlue(remainingBlue);
        requiredBlue -= deductedBlue;

        int remainingGreen = Math.max(0, playerPanel.getGemNumGreen() - requiredGreen);
        int deductedGreen = playerPanel.getGemNumGreen() - remainingGreen;
        playerPanel.setGemNumGreen(remainingGreen);
        requiredGreen -= deductedGreen;

        int remainingWhite = Math.max(0, playerPanel.getGemNumWhite() - requiredWhite);
        int deductedWhite = playerPanel.getGemNumWhite() - remainingWhite;
        playerPanel.setGemNumWhite(remainingWhite);
        requiredWhite -= deductedWhite;

        int remainingBlack = Math.max(0, playerPanel.getGemNumBlack() - requiredBlack);
        int deductedBlack = playerPanel.getGemNumBlack() - remainingBlack;
        playerPanel.setGemNumBlack(remainingBlack);
        requiredBlack -= deductedBlack;

        int remainingPink = Math.max(0, playerPanel.getGemNumPink() - requiredPink);
        int deductedPink = playerPanel.getGemNumPink() - remainingPink;
        playerPanel.setGemNumPink(remainingPink);
        requiredPink -= deductedPink;

        // 使用金色宝石来支付剩余的费用
        int totalRemainingRequired = requiredRed + requiredBlue + requiredGreen + requiredWhite + requiredBlack + requiredPink;
        int remainingGold = Math.max(0, playerPanel.getGemNumGold() - totalRemainingRequired);
        playerPanel.setGemNumGold(remainingGold);

        // 更新宝石总数
        playerPanel.setGemNumTotal(playerPanel.getGemNumTotal() - 
            (deductedRed + deductedBlue + deductedGreen + deductedWhite + deductedBlack + deductedPink + totalRemainingRequired));
    }

    /**
     * 从相同等级的卡片堆中随机将一个show值为false的卡片置为show=true（仅对buyable为true且keepable为true的卡片）
     * @param roomResource 房间资源
     * @param level 卡片等级
     */
    private void revealNextCard(RoomResource roomResource, int level) {
        List<card> cardList = null;
        
        // 根据等级获取对应的卡片列表
        switch (level) {
            case 1:
                cardList = roomResource.getCardListA();
                break;
            case 2:
                cardList = roomResource.getCardListB();
                break;
            case 3:
                cardList = roomResource.getCardListC();
                break;
            case 4:
                cardList = roomResource.getCardListD();
                break;
        }
        
        if (cardList == null || cardList.isEmpty()) {
            return;
        }
        
        // 查找所有show为false但buyable为true且keepable为true的卡片
        List<card> eligibleCards = new ArrayList<>();
        for (card card : cardList) {
            if (!card.isShow() && card.isBuyable() && card.isKeepable()) {
                eligibleCards.add(card);
            }
        }
        
        // 如果有符合条件的卡片，则随机选择一个显示
        if (!eligibleCards.isEmpty()) {
            Random random = new Random();
            int index = random.nextInt(eligibleCards.size());
            eligibleCards.get(index).setShow(true);
        }
    }

    /**
     * 克隆卡片对象
     * @param original 原始卡片
     * @return 克隆的卡片
     */
    private card cloneCard(card original) {
        card cloned = new card();
        cloned.setId(original.getId());
        cloned.setLevel(original.getLevel());
        cloned.setScore(original.getScore());
        cloned.setDiscountRed(original.getDiscountRed());
        cloned.setDiscountGreen(original.getDiscountGreen());
        cloned.setDiscountWhite(original.getDiscountWhite());
        cloned.setDiscountBlack(original.getDiscountBlack());
        cloned.setDiscountBlue(original.getDiscountBlue());
        cloned.setCostRed(original.getCostRed());
        cloned.setCostBlue(original.getCostBlue());
        cloned.setCostGreen(original.getCostGreen());
        cloned.setCostPink(original.getCostPink());
        cloned.setCostBlack(original.getCostBlack());
        cloned.setCostWhite(original.getCostWhite());
        cloned.setCrownsNum(original.getCrownsNum());
        cloned.setExtraReward(original.getExtraReward());
        cloned.setShow(original.isShow());
        cloned.setBuyable(original.isBuyable());
        cloned.setKeepable(original.isKeepable());
        return cloned;
    }

    /**
     * 创建默认游戏配置
     * @return 默认游戏配置
     */
    private GameConfig createDefaultGameConfig() {
        GameConfig config = new GameConfig();
        config.setGameMode("classic");
        config.setGameTimeLimit(600); // 10分钟
        config.setTurnTimeLimit(30); // 30秒
        config.setInitialGems(0);
        config.setInitialCards(5);
        config.setWinScore(100);
        config.setWinRound(20);
        return config;
    }

    /**
     * 为房间添加玩家
     * @param roomId 房间ID
     * @param playerIp 玩家IP
     */
    public void addPlayerToRoom(String roomId, String playerIp) {
        RoomResource roomResource = (RoomResource) redisService.get("roomResource:" + roomId);
        if (roomResource != null) {
            // 添加玩家IP
            roomResource.getPlayerIps().add(playerIp);
            
            // 初始化玩家面板
            userPanel panel = new userPanel();
            panel.setUserIp(playerIp);
            panel.setScore(0);
            panel.setCollectedGems(new ArrayList<>());
            panel.setReady(false);
            panel.setDiscountRed(0);
            panel.setDiscountBlue(0);
            panel.setDiscountGreen(0);
            panel.setDiscountWhite(0);
            panel.setDiscountBlack(0);
            panel.setGemNumRed(0);
            panel.setGemNumBlue(0);
            panel.setGemNumGreen(0);
            panel.setGemNumWhite(0);
            panel.setGemNumBlack(0);
            panel.setGemNumGold(0);
            panel.setGemNumPink(0);
            panel.setGemNumTotal(0);
            panel.setCardBought(new ArrayList<>());
            panel.setCardKept(new ArrayList<>());
            
            roomResource.getPlayerPanels().put(playerIp, panel);
            
            // 初始化玩家卡牌
            roomResource.getBuyCards().put(playerIp, new ArrayList<>());
            roomResource.getKeepCards().put(playerIp, new ArrayList<>());

            // 更新Redis中的房间资源
            redisService.set("roomResource:" + roomId, roomResource);
            
            // 通知客户端房间资源已更新
            notificationService.notifyRoomResourceUpdate(roomId, roomResource);
        }
    }

    /**
     * 获取房间资源
     * @param roomId 房间ID
     * @return 房间资源
     */
    public RoomResource getRoomResource(String roomId) {
        Object obj = redisService.get("roomResource:" + roomId);
        if (obj instanceof RoomResource) {
            return (RoomResource) obj;
        }
        return null;
    }

    /**
     * 更新房间资源
     * @param roomId 房间ID
     * @param roomResource 房间资源
     */
    public void updateRoomResource(String roomId, RoomResource roomResource) {
        redisService.set("roomResource:" + roomId, roomResource);
        
        // 通知客户端房间资源已更新
        notificationService.notifyRoomResourceUpdate(roomId, roomResource);
    }

    /**
     * 开始游戏
     * @param roomId 房间ID
     */
    public void startGame(String roomId) {
        RoomResource roomResource = getRoomResource(roomId);
        if (roomResource != null && "waiting".equals(roomResource.getStatus())) {
            // 设置房间状态为游戏中
            roomResource.setStatus("playing");
            
            // 设置当前回合和下一回合玩家
            List<String> playerIps = roomResource.getPlayerIps();
            if (playerIps != null && playerIps.size() >= 2) {
                // 随机选择一个玩家作为当前回合玩家
                Random random = new Random();
                int currentPlayerIndex = random.nextInt(playerIps.size());
                roomResource.setCurrentPlayerIp(playerIps.get(currentPlayerIndex));
                // 设置下一个回合玩家
                int nextPlayerIndex = (currentPlayerIndex + 1) % playerIps.size();
                roomResource.setNextPlayerIp(playerIps.get(nextPlayerIndex));
                
                // 设置回合数为1
                roomResource.setRound(1);

                // 第二个行动的玩家特权数+1
                roomResource.getPlayerPanels().get(playerIps.get(nextPlayerIndex)).setPrivilege(1);

                // 设置当前玩家可以使用特权
                roomResource.setCanUsePrivilege(true);
                // 设置当前玩家可以补充宝石盘
                roomResource.setCanRefillGemBoard(true);
                
                // 更新Redis中的房间资源
                updateRoomResource(roomId, roomResource);

                notificationService.notifyRoomCommand(roomId , "START_GAME");
            }
        }
    }

    /**
     * 玩家使用特权兑换宝石
     * @param roomId 房间ID
     * @param playerIp 玩家IP
     * @param gemPositionIndex 宝石在宝石盘中的位置索引
     */
    public void usePrivilegeToExchangeGem(String roomId, String playerIp, int gemPositionIndex) {
        RoomResource roomResource = getRoomResource(roomId);
        if (roomResource == null || !"playing".equals(roomResource.getStatus())) {
            return;
        }

        // 检查是否是当前回合玩家
        if (!playerIp.equals(roomResource.getCurrentPlayerIp())) {
            return;
        }

        // 检查该玩家的特权数是否大于0
        userPanel playerPanel = roomResource.getPlayerPanels().get(playerIp);
        if (playerPanel.getPrivilege() <= 0) {
            return;
        }

        // 检查宝石位置索引是否有效
        List<String> gemPositions = roomResource.getGemPositon();
        if (gemPositions == null || gemPositionIndex < 0 || gemPositionIndex >= gemPositions.size()) {
            return;
        }

        // 检查该位置是否有宝石
        String gemId = gemPositions.get(gemPositionIndex);
        if ("-1".equals(gemId)) {
            return;
        }

        // 检查宝石是否为金色宝石（特权不能兑换金色宝石）
        gem gem = findGemById(roomResource.getGemSource(), gemId);
        if (gem != null && gem.getColor() == GemColor.gold) {
            return;
        }

        // 执行兑换操作
        collectGemFromBoard(roomResource, playerIp, gemPositionIndex, gemId);
        
        // 玩家的特权数-1
        playerPanel.setPrivilege(playerPanel.getPrivilege() - 1);
        
        // 更新Redis中的房间资源
        updateRoomResource(roomId, roomResource);

        notificationService.notifyRoomCommand(roomId , "USE_PRIVILEGE_SUCCESS");
    }

    /**
     * 玩家保留卡片
     * @param roomId 房间ID
     * @param playerIp 玩家IP
     * @param cardId 卡片ID
     * @param goldGemPosition 黄金宝石在宝石盘的位置索引
     */
    public void reserveCard(String roomId, String playerIp, String cardId, Integer goldGemPosition) {
        RoomResource roomResource = getRoomResource(roomId);
        if (roomResource == null || !"playing".equals(roomResource.getStatus())) {
            return;
        }

        // 检查是否是当前回合玩家
        if (!playerIp.equals(roomResource.getCurrentPlayerIp())) {
            return;
        }

        // 查找要保留的卡片
        card cardToReserve = findCardById(roomResource, cardId);
        if (cardToReserve == null || !cardToReserve.isShow() || !cardToReserve.isKeepable()) {
            return; // 卡片不存在、未显示或不可保留
        }

        // 获取玩家面板
        Map<String, userPanel> playerPanels = roomResource.getPlayerPanels();
        userPanel playerPanel = playerPanels.get(playerIp);
        if (playerPanel == null) {
            return;
        }

        // 将卡片添加到玩家保留列表
        List<card> keptCards = playerPanel.getCardKept();
        if (keptCards == null) {
            keptCards = new ArrayList<>();
            playerPanel.setCardKept(keptCards);
        }
        keptCards.add(cloneCard(cardToReserve));


        // buyable保持为true

        // 从相同等级的卡片堆中随机将一个show值为false的卡片置为show=true
        revealNextCard(roomResource, cardToReserve.getLevel());

        // 更新卡片状态
        cardToReserve.setShow(false);
        cardToReserve.setKeepable(false); // 保留后将keepable设为false

        // 给玩家增加一个金色宝石
//        playerPanel.setGemNumGold(playerPanel.getGemNumGold() + 1);
//        playerPanel.setGemNumTotal(playerPanel.getGemNumTotal() + 1);
        
        // 玩家从指定位置拿取一个金色宝石
        if (goldGemPosition != null) {
            List<String> gemPositions = roomResource.getGemPositon();
            if (goldGemPosition >= 0 && goldGemPosition < gemPositions.size()) {
                String gemId = gemPositions.get(goldGemPosition);
                // 检查该位置是否有宝石
                if (!"-1".equals(gemId)) {
                    // 查找宝石对象
                    gem gem = findGemById(roomResource.getGemSource(), gemId);
                    // 检查是否为金色宝石
                    if (gem != null && gem.getColor() == GemColor.gold) {
                        // 从宝石盘拿取宝石并归玩家所有
                        collectGemFromBoard(roomResource, playerIp, goldGemPosition, gemId);
                    }
                }
            }
        }

        // 更新Redis中的房间资源
        updateRoomResource(roomId, roomResource);


        notificationService.notifyRoomCommand(roomId, "RESERVE_CARD_SUCCESS");
        
        // 进入下一回合
        startNewRound(roomId);
        
        // 为下一玩家设置操作权限
        setupNextPlayerPermissions(roomId);
    }

    /**
     * 开始新的回合
     * @param roomId 房间ID
     */
    public void startNewRound(String roomId) {
        RoomResource roomResource = getRoomResource(roomId);
        if (roomResource == null || !"playing".equals(roomResource.getStatus())) {
            return;
        }

        // 获取当前玩家IP
        String currentPlayerIp = roomResource.getCurrentPlayerIp();
        
        // 设置当前玩家为原来的下一个玩家
        String nextPlayerIp = roomResource.getNextPlayerIp();
        roomResource.setCurrentPlayerIp(nextPlayerIp);
        
        // 设置下一个玩家为另一个玩家（确保是另一个玩家）
        String opponentIp = findOpponentIp(roomResource, nextPlayerIp);
        if (opponentIp != null) {
            roomResource.setNextPlayerIp(opponentIp);
        }
        
        // 回合数增加
        roomResource.setRound(roomResource.getRound() + 1);

        // 重置当前玩家是否已补充宝石盘属性
        roomResource.setFilled(false);

        // 更新Redis中的房间资源
        updateRoomResource(roomId, roomResource);

        notificationService.notifyRoomCommand(roomId, "START_NEW_ROUND");
    }

    /**
     * 为下一玩家设置操作权限
     * @param roomId 房间ID
     */
    private void setupNextPlayerPermissions(String roomId) {
        RoomResource roomResource = getRoomResource(roomId);
        if (roomResource == null || !"playing".equals(roomResource.getStatus())) {
            return;
        }

        // 通知新回合玩家回合开始
        String currentPlayerIp = roomResource.getCurrentPlayerIp();
        if (currentPlayerIp != null) {
            notificationService.notifyRoomCommand(roomId, "PLAYER_TURN_STARTED:" + currentPlayerIp);
            
            // 设置新玩家可以使用特权
            roomResource.setCanUsePrivilege(true);
            
            // 设置新玩家可以补充宝石盘
            roomResource.setCanRefillGemBoard(true);
            
            // 更新Redis中的房间资源
            updateRoomResource(roomId, roomResource);
        }
    }

    /**
     * 再来一轮
     * @param roomId 房间ID
     */
    public void playAnotherRound(String roomId) {
        RoomResource roomResource = getRoomResource(roomId);
        if (roomResource == null || !"playing".equals(roomResource.getStatus())) {
            return;
        }

        // 修改下一回合执行者为当前回合执行者（即同一个玩家再执行一次）
        String currentPlayerIp = roomResource.getCurrentPlayerIp();
        roomResource.setNextPlayerIp(currentPlayerIp);
        
        // 回合数增加
        roomResource.setRound(roomResource.getRound() + 1);

        // 更新Redis中的房间资源
        updateRoomResource(roomId, roomResource);

        notificationService.notifyRoomCommand(roomId, "PLAY_ANOTHER_ROUND");
    }

    /**
     * 卡片变色
     * @param roomId 房间ID
     * @param playerIp 玩家IP
     * @param cardId 卡片ID
     * @param color 要设置的颜色
     */
    public void changeCardColor(String roomId, String playerIp, String cardId, String color) {
        RoomResource roomResource = getRoomResource(roomId);
        if (roomResource == null || !"playing".equals(roomResource.getStatus())) {
            return;
        }

        // 检查是否是当前回合玩家
        if (!playerIp.equals(roomResource.getCurrentPlayerIp())) {
            return;
        }

        // 查找要变色的卡片
        card cardToChange = findCardById(roomResource, cardId);
        if (cardToChange == null) {
            return; // 卡片不存在
        }

        // 获取玩家面板
        Map<String, userPanel> playerPanels = roomResource.getPlayerPanels();
        userPanel playerPanel = playerPanels.get(playerIp);
        if (playerPanel == null) {
            return;
        }

        // 检查玩家是否拥有这张卡片（在已购买或已保留的卡片中）
        boolean hasCard = false;
        
        // 检查已购买的卡片
        List<card> boughtCards = playerPanel.getCardBought();
        if (boughtCards != null) {
            for (card card : boughtCards) {
                if (cardId.equals(card.getId())) {
                    hasCard = true;
                    break;
                }
            }
        }
        
        // 如果玩家不拥有这张卡片，则不能进行变色操作
        if (!hasCard) {
            return;
        }

        // 将所有颜色折扣置为0
        cardToChange.setDiscountRed(0);
        cardToChange.setDiscountBlue(0);
        cardToChange.setDiscountGreen(0);
        cardToChange.setDiscountWhite(0);
        cardToChange.setDiscountBlack(0);

        // 根据指定颜色设置对应折扣为1
        switch (color.toLowerCase()) {
            case "red":
                cardToChange.setDiscountRed(1);
                break;
            case "blue":
                cardToChange.setDiscountBlue(1);
                break;
            case "green":
                cardToChange.setDiscountGreen(1);
                break;
            case "white":
                cardToChange.setDiscountWhite(1);
                break;
            case "black":
                cardToChange.setDiscountBlack(1);
                break;
            default:
                // 无效颜色，不进行任何操作
                return;
        }

        // 更新Redis中的房间资源
        updateRoomResource(roomId, roomResource);

        notificationService.notifyRoomCommand(roomId, "CHANGE_CARD_COLOR_SUCCESS");
    }

    /**
     * 获取对方玩家一个宝石
     * @param roomId 房间ID
     * @param playerIp 玩家IP
     * @param targetPlayerIp 目标玩家IP
     * @param gemColor 宝石颜色
     */
    public void takeGemFromOpponent(String roomId, String playerIp, String targetPlayerIp, String gemColor) {
        RoomResource roomResource = getRoomResource(roomId);
        if (roomResource == null || !"playing".equals(roomResource.getStatus())) {
            return;
        }

        // 检查是否是当前回合玩家
        if (!playerIp.equals(roomResource.getCurrentPlayerIp())) {
            return;
        }

        // 检查目标玩家是否为对手
        String opponentIp = findOpponentIp(roomResource, playerIp);
        if (opponentIp == null || !opponentIp.equals(targetPlayerIp)) {
            return;
        }

        // 获取玩家面板
        Map<String, userPanel> playerPanels = roomResource.getPlayerPanels();
        userPanel playerPanel = playerPanels.get(playerIp);
        userPanel opponentPanel = playerPanels.get(targetPlayerIp);
        
        if (playerPanel == null || opponentPanel == null) {
            return;
        }

        // 检查目标玩家是否拥有指定颜色的宝石
        int opponentGemCount = 0;
        switch (gemColor.toLowerCase()) {
            case "red":
                opponentGemCount = opponentPanel.getGemNumRed();
                if (opponentGemCount > 0) {
                    opponentPanel.setGemNumRed(opponentGemCount - 1);
                    playerPanel.setGemNumRed(playerPanel.getGemNumRed() + 1);
                }
                break;
            case "blue":
                opponentGemCount = opponentPanel.getGemNumBlue();
                if (opponentGemCount > 0) {
                    opponentPanel.setGemNumBlue(opponentGemCount - 1);
                    playerPanel.setGemNumBlue(playerPanel.getGemNumBlue() + 1);
                }
                break;
            case "green":
                opponentGemCount = opponentPanel.getGemNumGreen();
                if (opponentGemCount > 0) {
                    opponentPanel.setGemNumGreen(opponentGemCount - 1);
                    playerPanel.setGemNumGreen(playerPanel.getGemNumGreen() + 1);
                }
                break;
            case "white":
                opponentGemCount = opponentPanel.getGemNumWhite();
                if (opponentGemCount > 0) {
                    opponentPanel.setGemNumWhite(opponentGemCount - 1);
                    playerPanel.setGemNumWhite(playerPanel.getGemNumWhite() + 1);
                }
                break;
            case "black":
                opponentGemCount = opponentPanel.getGemNumBlack();
                if (opponentGemCount > 0) {
                    opponentPanel.setGemNumBlack(opponentGemCount - 1);
                    playerPanel.setGemNumBlack(playerPanel.getGemNumBlack() + 1);
                }
                break;
            case "pink":
                opponentGemCount = opponentPanel.getGemNumPink();
                if (opponentGemCount > 0) {
                    opponentPanel.setGemNumPink(opponentGemCount - 1);
                    playerPanel.setGemNumPink(playerPanel.getGemNumPink() + 1);
                }
                break;
            case "gold":
                opponentGemCount = opponentPanel.getGemNumGold();
                if (opponentGemCount > 0) {
                    opponentPanel.setGemNumGold(opponentGemCount - 1);
                    playerPanel.setGemNumGold(playerPanel.getGemNumGold() + 1);
                }
                break;
            default:
                // 无效颜色，不进行任何操作
                return;
        }

        // 更新宝石总数
        if (opponentGemCount > 0) {
            opponentPanel.setGemNumTotal(opponentPanel.getGemNumTotal() - 1);
            playerPanel.setGemNumTotal(playerPanel.getGemNumTotal() + 1);

            // 更新Redis中的房间资源
            updateRoomResource(roomId, roomResource);

            notificationService.notifyRoomCommand(roomId, "TAKE_GEM_FROM_OPPONENT_SUCCESS");
        }
    }

    /**
     * 玩家获取特权
     * @param roomId 房间ID
     * @param playerIp 玩家IP
     */
    public void gainPrivilege(String roomId, String playerIp) {
        RoomResource roomResource = getRoomResource(roomId);
        if (roomResource == null || !"playing".equals(roomResource.getStatus())) {
            return;
        }

        // 检查是否是当前回合玩家
        if (!playerIp.equals(roomResource.getCurrentPlayerIp())) {
            return;
        }

        // 获取玩家面板
        Map<String, userPanel> playerPanels = roomResource.getPlayerPanels();
        userPanel currentPlayerPanel = playerPanels.get(playerIp);
        if (currentPlayerPanel == null) {
            return;
        }

        // 如果该玩家的特权数已经达到3个，则不做处理
        if (currentPlayerPanel.getPrivilege() >= 3) {
            return;
        }

        // 增加玩家特权数
        currentPlayerPanel.setPrivilege(currentPlayerPanel.getPrivilege() + 1);

        // 如果公共特权数不为0，则公共特权数-1
        if (roomResource.getPublicPrivilege() > 0) {
            roomResource.setPublicPrivilege(roomResource.getPublicPrivilege() - 1);
        } else {
            // 如果公共特权数为0且对手有特权数，则对手特权数-1
            String opponentIp = findOpponentIp(roomResource, playerIp);
            if (opponentIp != null) {
                userPanel opponentPanel = playerPanels.get(opponentIp);
                if (opponentPanel != null && opponentPanel.getPrivilege() > 0) {
                    opponentPanel.setPrivilege(opponentPanel.getPrivilege() - 1);
                }
            }
        }

        // 更新Redis中的房间资源
        updateRoomResource(roomId, roomResource);

        notificationService.notifyRoomCommand(roomId , "GET_PRIVILEGE_SUCCESS");
    }

    /**
     * 查找对手IP
     * @param roomResource 房间资源
     * @param currentPlayerIp 当前玩家IP
     * @return 对手IP，如果未找到则返回null
     */
    private String findOpponentIp(RoomResource roomResource, String currentPlayerIp) {
        List<String> playerIps = roomResource.getPlayerIps();
        if (playerIps == null || playerIps.size() != 2) {
            return null;
        }

        for (String playerIp : playerIps) {
            if (!currentPlayerIp.equals(playerIp)) {
                return playerIp;
            }
        }
        return null;
    }

    /**
     * 计算玩家某种颜色折扣的卡片总分数
     * @param cards 玩家购买的卡片列表
     * @param color 颜色
     * @return 该颜色折扣卡片的总分数
     */
    private int calculateColorDiscountScore(List<card> cards, String color) {
        if (cards == null || color == null) {
            return 0;
        }

        int totalScore = 0;
        for (card card : cards) {
            // 检查卡片是否有指定颜色的折扣
            boolean hasColorDiscount = false;
            switch (color.toLowerCase()) {
                case "red":
                    hasColorDiscount = card.getDiscountRed() > 0;
                    break;
                case "blue":
                    hasColorDiscount = card.getDiscountBlue() > 0;
                    break;
                case "green":
                    hasColorDiscount = card.getDiscountGreen() > 0;
                    break;
                case "white":
                    hasColorDiscount = card.getDiscountWhite() > 0;
                    break;
                case "black":
                    hasColorDiscount = card.getDiscountBlack() > 0;
                    break;
            }

            // 如果有该颜色的折扣，则累加分数
            if (hasColorDiscount) {
                totalScore += card.getScore();
            }
        }
        return totalScore;
    }

    /**
     * 检查游戏是否结束并确定获胜者
     * @param roomResource 房间资源
     * @param roomId 房间ID
     * @param playerIp 当前玩家IP
     */
    private void checkGameEndConditions(RoomResource roomResource, String roomId, String playerIp) {
        Map<String, userPanel> playerPanels = roomResource.getPlayerPanels();
        userPanel currentPlayerPanel = playerPanels.get(playerIp);
        
        if (currentPlayerPanel == null) {
            return;
        }

        // 条件1: 玩家购买的卡片中某种颜色折扣的卡片总分数达到10
        List<card> boughtCards = currentPlayerPanel.getCardBought();
        if (boughtCards != null) {
            boolean colorScoreReached = false;
            String[] colors = {"red", "blue", "green", "white", "black"};
            
            for (String color : colors) {
                int colorScore = calculateColorDiscountScore(boughtCards, color);
                if (colorScore >= 10) {
                    colorScoreReached = true;
                    break;
                }
            }
            
            if (colorScoreReached) {
                notificationService.notifyRoomCommand(roomId, "GAME_END_WIN_BY_COLOR_SCORE:" + playerIp);
                return;
            }
        }

        // 条件2: 玩家总分数达到了20
        if (currentPlayerPanel.getScore() >= 20) {
            notificationService.notifyRoomCommand(roomId, "GAME_END_WIN_BY_SCORE:" + playerIp);
            return;
        }

        // 条件3: 玩家的皇冠数达到了10
        if (currentPlayerPanel.getCrownsNum() >= 10) {
            notificationService.notifyRoomCommand(roomId, "GAME_END_WIN_BY_CROWNS:" + playerIp);
            return;
        }
    }

    /**
     * 补充宝石盘
     * 将黑袋中宝石按随机顺序补充到当前宝石盘的空位中
     * 补充路径为从5*5的宝石盘最中心出发，最初方向朝上，顺时针螺旋式填充
     * @param roomId 房间ID
     */
    public void refillGemBoard(String roomId) {
        RoomResource roomResource = getRoomResource(roomId);
        if (roomResource == null) {
            return;
        }

        // 获取宝石盘位置和黑袋
        List<String> gemPositions = roomResource.getGemPositon();
        List<gem> blackBag = roomResource.getBlackBag();

        // 如果黑袋为空，直接返回
        if (blackBag == null || blackBag.isEmpty()) {
            return;
        }

        // 随机打乱黑袋中的宝石
        Collections.shuffle(blackBag);

        // 定义螺旋填充路径（从中心12开始，向上移动，顺时针螺旋）
        int[] spiralPath = {12, 7, 8, 13, 18, 17, 16, 11, 6, 1, 2, 3, 4, 9, 14, 19, 24, 23, 22, 21, 20, 15, 10, 5, 0};

        // 按螺旋路径顺序填充空位
        int blackBagIndex = 0;
        for (int position : spiralPath) {
            // 如果该位置为空且黑袋还有宝石，则填充
            if ("-1".equals(gemPositions.get(position)) && blackBagIndex < blackBag.size()) {
                gem gemToPlace = blackBag.get(blackBagIndex);
                gemPositions.set(position, gemToPlace.getId());
                blackBagIndex++;
            }
        }

        // 从黑袋中移除已使用的宝石（前blackBagIndex个）
        if (blackBagIndex > 0) {
            blackBag.subList(0, blackBagIndex).clear();
        }

        // 给予对手一个特权
        String currentPlayerIp = roomResource.getCurrentPlayerIp();
        if (currentPlayerIp != null) {
            String opponentIp = findOpponentIp(roomResource, currentPlayerIp);
            if (opponentIp != null) {
                // 给予对手特权（不检查是否是当前回合玩家，因为这是补充宝石盘的副作用）
                gainPrivilegeToPlayer(roomResource, roomId, opponentIp);
            }
        }

        // 记录此回合进行了宝石盘填充
        roomResource.setFilled(true);
        
        // 设置当前玩家不能再补充宝石盘
        roomResource.setCanRefillGemBoard(false);
        
        // 设置当前玩家不能再使用特权
        roomResource.setCanUsePrivilege(false);

        // 更新Redis中的房间资源
        updateRoomResource(roomId, roomResource);

        // 通知客户端宝石盘已更新
        notificationService.notifyRoomCommand(roomId, "GEM_BOARD_REFILLED");
    }

    /**
     * 给予玩家特权（内部方法，不检查是否是当前回合玩家）
     * @param roomResource 房间资源
     * @param roomId 房间ID
     * @param playerIp 玩家IP
     */
    private void gainPrivilegeToPlayer(RoomResource roomResource, String roomId, String playerIp) {
        // 获取玩家面板
        Map<String, userPanel> playerPanels = roomResource.getPlayerPanels();
        userPanel playerPanel = playerPanels.get(playerIp);
        if (playerPanel == null) {
            return;
        }

        // 如果该玩家的特权数已经达到3个，则不做处理
        if (playerPanel.getPrivilege() >= 3) {
            return;
        }

        // 增加玩家特权数
        playerPanel.setPrivilege(playerPanel.getPrivilege() + 1);

        // 如果公共特权数不为0，则公共特权数-1
        if (roomResource.getPublicPrivilege() > 0) {
            roomResource.setPublicPrivilege(roomResource.getPublicPrivilege() - 1);
        } else {
            // 如果公共特权数为0且对手有特权数，则对手特权数-1
            String opponentIp = findOpponentIp(roomResource, playerIp);
            if (opponentIp != null) {
                userPanel opponentPanel = playerPanels.get(opponentIp);
                if (opponentPanel != null && opponentPanel.getPrivilege() > 0) {
                    opponentPanel.setPrivilege(opponentPanel.getPrivilege() - 1);
                }
            }
        }
        
        // 通知客户端特权获取成功
        notificationService.notifyRoomCommand(roomId, "GET_PRIVILEGE_SUCCESS");
    }

    /**
     * 切换玩家准备状态
     * @param roomId 房间ID
     * @param playerIp 玩家IP
     */
    public void togglePlayerReady(String roomId, String playerIp) {
        RoomResource roomResource = getRoomResource(roomId);
        if (roomResource != null) {
            // 获取玩家面板
            Map<String, userPanel> playerPanels = roomResource.getPlayerPanels();
            userPanel playerPanel = playerPanels.get(playerIp);
            
            if (playerPanel != null) {
                // 切换玩家准备状态（取反）
                playerPanel.setReady(!playerPanel.isReady());
                
                // 更新Redis中的房间资源
                updateRoomResource(roomId, roomResource);
                
                // 通知客户端房间资源已更新
                notificationService.notifyRoomResourceUpdate(roomId, roomResource);
            }
        }
    }
}